/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __K_MQ_H__
#define __K_MQ_H__

/* includes (standard library, system) ---------------------------------------*/
#include <stddef.h>
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <x_list.h>

#include <k_sem.h>
#include <k_mutex.h>
#include <k_errno.h>
#include <k_obj.h>
/* includes (local) ----------------------------------------------------------*/

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* defines -------------------------------------------------------------------*/

#define MQ_OP_RD 0
#define MQ_OP_WT 1

#define ERRNO_MQ_ILLEGAL_ID        ERRNO_JOIN(MID_MQ, 1)
#define ERRNO_MQ_ILLEGAL_SIZE      ERRNO_JOIN(MID_MQ, 2)
#define ERRNO_MQ_ILLEGAL_MSGS      ERRNO_JOIN(MID_MQ, 3)
#define ERRNO_MQ_ILLEGAL_BUFF      ERRNO_JOIN(MID_MQ, 4)
#define ERRNO_MQ_ILLEGAL_OPERATION ERRNO_JOIN(MID_MQ, 5)
#define ERRNO_MQ_UNAVAILABLE       ERRNO_JOIN(MID_MQ, 6)
#define ERRNO_MQ_TIMEOUT           ERRNO_JOIN(MID_MQ, 7)

/* typedefs ------------------------------------------------------------------*/

typedef struct mq {
    obj_t obj;
    sem_t sem[2]; /* 0: rdsem, 1: wtsem */
    size_t msg_size;
    size_t max_msgs;
    atomic_uint idx[2]; /* 0: head,  1: tail  */
    char *msgs;
} mq_t, *mq_id;

/* macro ---------------------------------------------------------------------*/
/* inlines -------------------------------------------------------------------*/
/* externs -------------------------------------------------------------------*/

extern mq_id mq_create(size_t msg_size, size_t max_msgs, unsigned int options);
extern int mq_delete(mq_id mq);
extern mq_id mq_open(const char *name, int oflag, ...);
extern int mq_timedsend(mq_id mq, void *buf, size_t size, unsigned int timeout);
extern int mq_send(mq_id mq, void *buf, size_t size);
extern int mq_trysend(mq_id mq, void *buf, size_t size);
extern int mq_timedrecv(mq_id mq, void *buf, size_t size, unsigned int timeout);
extern int mq_recv(mq_id mq, void *buf, size_t size);
extern int mq_tryrecv(mq_id mq, void *buf, size_t size);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __K_MQ_H__ */
